// package: learn-go
// filename: gf_demo
// author: Administrator@gmail.com
// time: 2023/9/16 20:12
package main

import (
	"context"
	"fmt"
	"time"
)

type Queue struct {
	Channel chan interface{}
	Buffer  []interface{}
}

func NewQueue(size int) *Queue {
	return &Queue{
		Channel: make(chan interface{}, size),
		Buffer:  make([]interface{}, 0, size),
	}
}

func (q *Queue) Add(value int) {
	select {
	case q.Channel <- value:
		// Value sent successfully
	case <-time.After(5 * time.Second):
		// Timeout after 5 seconds
		fmt.Println("Timeout when trying to add value to the queue")
	}
}

func (q *Queue) GetBatch(ctx context.Context, batchSize int) []interface{} {
	result := make([]interface{}, 0, batchSize)
	retryCount := 0
	for i := 0; i < batchSize; i++ {
		select {
		case value := <-q.Channel:
			result = append(result, value)
			q.Buffer = append(q.Buffer, value) // Add to buffer
		case <-ctx.Done():
			// Context cancelled or timeout reached
			fmt.Println("Context cancelled or timeout reached")
			return result
		case <-time.After(5 * time.Second):
			// Retry after 5 seconds
			retryCount++
			if retryCount >= 10 {
				fmt.Println("Maximum retry count reached")
				return result
			}
			continue
		}
	}
	return result
}

func main() {
	q := NewQueue(200)
	for i := 0; i < 100; i++ {
		q.Add(i)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	batch := q.GetBatch(ctx, 100)
	for _, v := range batch {
		fmt.Println(v)
	}
}
